package com.sl.water.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.http.ContentType;
import com.sl.common.utils.CommonFile;
import com.sl.water.service.AttachService;
import com.sl.water.vo.AttachVO;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

@Service
public class AttachServiceImpl implements AttachService {
    @Value("${file.dirPath:}")
    private String dirPath;

    @Override
    public ResponseEntity<?> upload(String kind, MultipartFile file) {
        try {
            if (file == null || file.isEmpty()) {
                return ResponseEntity.badRequest().body("上传文件不能为空");
            }
            // 构建存储路径
            String originalFileName = file.getOriginalFilename();
            String fileExtension = FileUtil.extName(originalFileName);
            String saveFileName = CommonFile.generateUniqueFileName(fileExtension);
            String relativePath = DateUtil.today().replace("-", "/");
            if (StringUtils.isNotEmpty(kind)) {
                relativePath = kind + "/" + relativePath;
            }
            File saveDir = FileUtil.file(dirPath, relativePath);
            FileUtil.mkdir(saveDir);

            // 保存文件
            File saveFile = FileUtil.file(saveDir, saveFileName);
            file.transferTo(saveFile);

            // 返回结果
            AttachVO result = new AttachVO();
            result.setFileName(originalFileName);
            result.setFileSize(FileUtil.readableFileSize(saveFile.length()));
            result.setAccessUrl(relativePath + "/" + saveFileName);
//            Map<String, Object> result = new HashMap<>();
//            result.put("originalFileName", originalFileName);
//            result.put("saveFileName", saveFileName);
//            result.put("relativePath", relativePath);
//            result.put("fileSize", FileUtil.readableFileSize(saveFile.length()));
//            result.put("accessUrl", relativePath + "/" + saveFileName);
            return ResponseEntity.ok(result);
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("文件上传失败：" + e.getMessage());
        }
    }

    @Override
    public ResponseEntity<?> upload(String kind, String fileName, MultipartFile file) {
        try {
            if (file == null || file.isEmpty()) {
                return ResponseEntity.badRequest().body("上传文件不能为空");
            }

            File saveDir = FileUtil.file(dirPath, kind);
            FileUtil.mkdir(saveDir);
            // 保存文件
            File saveFile = FileUtil.file(saveDir, fileName);
            file.transferTo(saveFile);

            // 返回结果
            AttachVO result = new AttachVO();
            result.setFileName(fileName);
            result.setFileSize(FileUtil.readableFileSize(saveFile.length()));
            result.setAccessUrl(kind + "/" + fileName);
            return ResponseEntity.ok(result);
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("文件上传失败：" + e.getMessage());
        }
    }

    @Override
    public void downloadFile(String path, HttpServletResponse response) {
        File file = FileUtil.file(dirPath, path);
        if (!FileUtil.exist(file)) {
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return;
        }

        try (InputStream in = new FileInputStream(file);
             OutputStream out = response.getOutputStream()) {
            // 设置响应头
            String fileName = URLEncoder.encode(file.getName(), StandardCharsets.UTF_8);
            response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileName + "\"");
            response.setContentType(ContentType.OCTET_STREAM.getValue());
            response.setContentLengthLong(file.length());
            IoUtil.copy(in, out);
        } catch (Exception e) {
            e.printStackTrace();
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        }
    }

    @Override
    public ResponseEntity<byte[]> previewFile(String path, HttpServletResponse response) {
        File file = FileUtil.file(dirPath, path);
        if (!FileUtil.exist(file)) {
            return ResponseEntity.notFound().build();
        }
        try {
            String fileSuffix = path.substring(path.lastIndexOf("."));
            ResponseEntity.BodyBuilder builder = ResponseEntity.ok();
            builder.contentLength(file.length());
            if (fileSuffix.toLowerCase().matches(".png|.jpg|.jpeg|.bmp|.gif|.icon")) {
                builder.cacheControl(CacheControl.noCache()).contentType(MediaType.IMAGE_PNG);
            } else if (fileSuffix.toLowerCase().matches(
                    ".flv|.swf|.mkv|.avi|.rm|.rmvb|.mpeg|.mpg|.ogg|.ogv|.mov|.wmv|.mp4|.webm|.wav|.mid|.mp3|.aac")) {
                builder.header("Content-Type", "video/mp4; charset=UTF-8");
            } else if (fileSuffix.toLowerCase().matches(".pdf")) {
                builder.header("Content-Type", "application/pdf; charset=UTF-8");
            }
            return builder.body(CommonFile.readFileToByteArray(file));
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }
    }

    // 根据文件名获取内容类型
    private String getContentType(String fileName) {
        String extension = FileUtil.extName(fileName).toLowerCase();
        switch (extension) {
            case "jpg":
            case "jpeg":
                return "image/jpeg";
            case "png":
                return "image/png";
            case "gif":
                return "image/gif";
            case "pdf":
                return "application/pdf";
            case "txt":
                return "text/plain";
            case "html":
            case "htm":
                return "text/html";
            case "css":
                return "text/css";
            case "js":
                return "application/javascript";
            case "json":
                return "application/json";
            case "xml":
                return "application/xml";
            case "mp4":
                return "video/mp4";
            case "mp3":
                return "audio/mpeg";
            default:
                return "application/octet-stream";
        }
    }
}
